package cn.com.open.itembank.service.impl;

import cn.com.open.itembank.common.GlobalConst;
import cn.com.open.itembank.common.enums.AnswerType;
import cn.com.open.itembank.common.enums.Source;
import cn.com.open.itembank.common.enums.YesOrNo;
import cn.com.open.itembank.dto.*;
import cn.com.open.itembank.entity.*;
import cn.com.open.itembank.mapper.PaperReadMapper;
import cn.com.open.itembank.mapper.PaperWriteMapper;
import cn.com.open.itembank.mapper.RulesMapper;
import cn.com.open.itembank.service.*;
import cn.com.open.itembank.utils.DateUtil;
import cn.com.open.itembank.utils.StringUtil;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.*;

@Component
public class GenerateCreateTestPaperUtil implements GenerateCreateTestPaper {

    @Autowired
    private ItemBankRemoteService itemBankService;
    @Autowired
    private QtiRemoteService qtiService;
    @Autowired
    private ItemRemoteService itemService;
    @Autowired
    private ComposeLogicRemoteService composeLogicRemoteService;
    @Autowired
    private PaperService paperService;
    @Autowired
    private PaperWriteMapper writePaperMapper;
    @Autowired
    private PaperReadMapper readPaperMapper;

    public ReturnModel generateCreateTestPaper(AsyncRule asyncRule) {

        ReturnModel model = new ReturnModel();
        //构建策略对象
        ComposePaper composePaper = new ComposePaper();
        composePaper.setRuleSaveModel(asyncRule.getRuleSaveModel());

        //根据试题数量查询模型获取指定条件下试题数量
        Map<String, QuestionCountFilterModel> checkQuestionCountMap = (Map<String, QuestionCountFilterModel>) asyncRule.getCheckRuleModel().getData();
        //可选试题列表
        Map<String, List<RuleQuestionModel>> forChooseQuestionListMap = itemService.getQuestionForRule(checkQuestionCountMap);
        //获取所有试题列表
        List<RuleQuestionModel> forChooseQuestionList = new ArrayList<>();

        for (Map.Entry<String, List<RuleQuestionModel>> map : forChooseQuestionListMap.entrySet()) {
            forChooseQuestionList.addAll(map.getValue());
        }
        //赋值所有可选试题列表
        composePaper.getForChooseQuestionList().addAll(forChooseQuestionList);
        //组装题型类别map
        Map<String, String> typeCategories = new HashMap<>();
        for (Map.Entry<String, QuestionCountFilterModel> map : checkQuestionCountMap.entrySet()) {
            QuestionCountFilterModel filterModel = map.getValue();
            String questionTypeID = filterModel.getQuestionTypeID();
            String questionCategoryIDs = filterModel.getQuestionCategoryIDs();
            if (typeCategories.containsKey(questionTypeID)) {
                String origin = typeCategories.get(questionTypeID);
                typeCategories.replace(questionTypeID, String.format("%s,%s", origin, questionCategoryIDs));
            } else {
                typeCategories.put(questionTypeID, questionCategoryIDs);
            }
        }
        //根据题库id，题型id，所属类别id查询试题id列表
        Map<String, List<String>> questionIdListByTypeAndCategoriesMap = itemService.getQuestionsByCategoriesForRules(asyncRule.getItemBankId(), typeCategories);
        //赋值试题id列表
        composePaper.getQuestionIdListByTypeAndCategories().putAll(questionIdListByTypeAndCategoriesMap);

        //获取题型集合
        List<QuestionTypeManageDto> questionTypeList = itemBankService.getQuestionTypeListByItemBankIdAndName(asyncRule.getItemBankId(), "");
        if (questionTypeList.size() == YesOrNo.NO.getIndex()) {
            model.setCode(GlobalConst.COURSE_NOT_EXIST);
            model.setMessage("题库不存在");
            return model;
        }
        //赋值题型集合
        composePaper.getQuestionTypes().addAll(questionTypeList);
        //题库信息
        CourseItemBank itemBank = itemBankService.getCourseItemBankInfo(asyncRule.getItemBankId());
        //
        Map<String, Object> paperItemsMap = new HashMap<>();

        //入库操作
        StringBuilder paperidStr = new StringBuilder();
        for (int i = 1; i <= asyncRule.getPaperCount(); i++) {
            //返回的组卷信息
            TestPaperModel testPaperModel = composeLogicRemoteService.composePaperGenetic(composePaper);

            if (testPaperModel == null) {
                testPaperModel = new TestPaperModel();
            }

            String testPaperID = UUID.randomUUID().toString();
            TestPaper testPaper = getInsertPaper(testPaperID, asyncRule.getItemBankId(), "", asyncRule.getPaperName(), itemBank.getCreateOrgID(), itemBank);
            PaperModel paperModel = new PaperModel();
            paperModel.setP1(testPaper.getTestPaperID());
            paperModel.setP2(testPaper.getTestPaperName());
            paperModel.setP3(testPaper.getCourseID());
            paperModel.setP4(testPaper.getOrganizationID());
            paperModel.setP5(Double.valueOf(testPaper.getScore()));
            paperModel.setP6(testPaper.getCreater());

            testPaperModel.setModel(paperModel);

            for (PaperPart paperPart : testPaperModel.getParts()) {
                for (PaperSection paperSection : paperPart.getSections()) {
                    for (PaperItem paperItem : paperSection.getItems()) {
                        updateQuestionDisplay(testPaperID, paperItem.getItemId(), true, DateUtil.toShowString(new Date()));
                        paperItemsMap.put("I1", paperItem.getItemId());
                        paperItemsMap.put("I9", paperItem.getScore());
                        testPaperModel.getItems().add(paperItemsMap);
                    }
                }
            }

            Map<String, Object> getEditQuestionXml = qtiService.getFullPaperXml(testPaperModel);
            //保存
            saveInsertTestPaper(getEditQuestionXml.get("xml").toString(), testPaper);

            paperidStr.append(testPaperID).append((i == asyncRule.getPaperCount() ? "" : ","));
        }
        model.setCode(GlobalConst.SUCCESS);
        model.setData(paperidStr);
        return model;
    }


    //region 形成试卷模型

    /**
     * 形成试卷模型.
     *
     * @param paperId    试卷id
     * @param itemBankId 题库id
     * @param creater    创建人id
     * @param paperName  试卷名称
     * @param itemBank   题库模型
     * @param oid        机构id
     * @return the insert paper
     */
    public TestPaper getInsertPaper(String paperId, String itemBankId, String creater, String paperName, String oid, CourseItemBank itemBank) {
        TestPaper paperInfo = new TestPaper();

        paperInfo.setTestPaperID(paperId);
        paperInfo.setTestPaperName(paperName);
        paperInfo.setMode(0);
        paperInfo.setTestPaperVersion(1);
        paperInfo.setCourseID(itemBankId);
        paperInfo.setScore("0");
        paperInfo.setState(YesOrNo.YES.getIndex());
        paperInfo.setCreater(creater);
        paperInfo.setCreateTime(DateUtil.toShowString(new Date()));
        paperInfo.setComment(null);
        paperInfo.setIsPublish(YesOrNo.YES.getIndex());
        paperInfo.setDisplayCount(0);
        paperInfo.setCreater("");
        paperInfo.setChecker("");
        paperInfo.setComment("");
        paperInfo.setIsCheck(YesOrNo.NO.getIndex());
        paperInfo.setSource(Source.INNER.getIndex());
        if (itemBank.getSource() == Source.OUTER.getIndex()) {
            paperInfo.setIsCheck(YesOrNo.YES.getIndex());
            paperInfo.setSource(Source.OUTER.getIndex());
        }

        paperInfo.setOrganizationID(!StringUtils.isEmpty(oid) ? oid : null);

        return paperInfo;
    }

    //endregion

    //region 新增试卷保存

    /**
     * 新增试卷保存.
     *
     * @param qtiXml    qti xml
     * @param testPaper the test paper
     * @return the int
     */
    public int saveInsertTestPaper(String qtiXml, TestPaper testPaper) {
        TestPaperContent content = new TestPaperContent();
        content.setTestPaperID(testPaper.getTestPaperID());
        content.setContentXml(qtiXml);

        if(StringUtil.isEmpty(testPaper.getOrganizationID())){
            testPaper.setOrganizationID("00000000-0000-0000-0000-000000000000");
        }
        int isSuccess = writePaperMapper.insertTestPaperContent(content);

        if (isSuccess > 0) {
            writePaperMapper.insertTestPaperModel(testPaper);
        }

        updateJson(testPaper.getCourseID(), testPaper.getTestPaperID());

        return GlobalConst.SUCCESS;
    }
    //endregion

    //region 更新试卷表json

    /**
     * 更新试卷表json.
     *
     * @param itemBankId the item bank id
     * @param id         the id
     */
    public void updateJson(String itemBankId, String id) {
        ReturnModel testPaperModel = paperService.getTestPaper(itemBankId, id, AnswerType.ALL, true);
        String jsonString = JSON.toJSONString(testPaperModel.getData());
        writePaperMapper.updateContentJSON(jsonString, id);
    }

    //endregion

    //region 更新试题曝光信息

    /**
     * 更新试题曝光信息
     *
     * @param id         试卷编号
     * @param questionId 试题编号
     * @param isIncrease 增加/减少：t/f
     * @param newDate    当前时间
     * @return
     */
    public int updateQuestionDisplay(String id, String questionId, boolean isIncrease, String newDate) {
        Question question = itemService.getItem(questionId);

        if (question == null) {
            return GlobalConst.ID_NOT_EXIST;
        }

        if (isIncrease) {
            // 增加曝光次数，则更新试题表曝光时间和次数加1，
            question.setDisplayCount(question.getDisplayCount() + 1);
            question.setDisplayTime(String.valueOf(newDate));

            //查询是否存在试题试卷关系表
            QuestionDisplayInfo displayInfolist = readPaperMapper.getQuestionDisplayByPaper(id, questionId);

            if (displayInfolist != null) {
                writePaperMapper.updateQuestionDisplayInfo(id, questionId, DateUtil.toShowString(new Date()));
            } else {
                writePaperMapper.insertQuestionDisplayInfo(id, questionId, newDate);
            }
        } else {
            // 减少曝光次数，则试题表次数减一（不得小于0）曝光时间修订至上一个曝光时间
            Date time;
            //查询最近一次曝光时间
            Date displayTime = readPaperMapper.getMaxQuestionDisplayTime(id, questionId);

            if (displayTime == null) {
                Calendar calendar = new GregorianCalendar(1900, 01, 01, 0, 0, 0);
                time = calendar.getTime();
            } else {
                time = displayTime;
            }

            if (0 < question.getDisplayCount()) {
                question.setDisplayCount(question.getDisplayCount() - 1);
                question.setDisplayTime(DateUtil.toShowString(time));
            }
        }

        // 如果试题曝光次数小于等于零，则删除试题相关的曝光数据
        if (0 >= question.getDisplayCount()) {
            writePaperMapper.deleteQuestionDisplayInfo(questionId);
        }

        writePaperMapper.updateQuestionDisplayTime(questionId, question.getDisplayCount(), question.getDisplayTime());

        return GlobalConst.SUCCESS;
    }
    //endregion

}
